package main

import (
	"fmt"
	"time"
)

/*
+	相加	A + B 输出结果 30
-	相减	A - B 输出结果 -10
*	相乘	A * B 输出结果 200
/	相除	B / A 输出结果 2
%	求余	B % A 输出结果 0
++	自增	A++ 输出结果 11
--	自减	A-- 输出结果 9

==	检查两个值是否相等，如果相等返回 True 否则返回 False。	(A == B) 为 False
!=	检查两个值是否不相等，如果不相等返回 True 否则返回 False。	(A != B) 为 True
>	检查左边值是否大于右边值，如果是返回 True 否则返回 False。	(A > B) 为 False
<	检查左边值是否小于右边值，如果是返回 True 否则返回 False。	(A < B) 为 True
>=	检查左边值是否大于等于右边值，如果是返回 True 否则返回 False。	(A >= B) 为 False
<=	检查左边值是否小于等于右边值，如果是返回 True 否则返回 False。	(A <= B) 为 True

&&	逻辑 AND 运算符。 如果两边的操作数都是 True，则条件 True，否则为 False。	(A && B) 为 False
||	逻辑 OR 运算符。 如果两边的操作数有一个 True，则条件 True，否则为 False。	(A || B) 为 True
!	逻辑 NOT 运算符。 如果条件为 True，则逻辑 NOT 条件 False，否则为 True。	!(A && B) 为 True

&	按位与运算符"&"是双目运算符。 其功能是参与运算的两数各对应的二进位相与。	(A & B) 结果为 12, 二进制为 0000 1100
|	按位或运算符"|"是双目运算符。 其功能是参与运算的两数各对应的二进位相或	(A | B) 结果为 61, 二进制为 0011 1101
^	按位异或运算符"^"是双目运算符。 其功能是参与运算的两数各对应的二进位相异或，当两对应的二进位相异时，结果为1。	(A ^ B) 结果为 49, 二进制为 0011 0001
<<	左移运算符"<<"是双目运算符。左移n位就是乘以2的n次方。 其功能把"<<"左边的运算数的各二进位全部左移若干位，由"<<"右边的数指定移动的位数，高位丢弃，低位补0。	A << 2 结果为 240 ，二进制为 1111 0000
>>	右移运算符">>"是双目运算符。右移n位就是除以2的n次方。 其功能是把">>"左边的运算数的各二进位全部右移若干位，">>"右边的数指定移动的位数。	A >> 2 结果为 15 ，二进制为 0000 1111

=	简单的赋值运算符，将一个表达式的值赋给一个左值	C = A + B 将 A + B 表达式结果赋值给 C
+=	相加后再赋值	C += A 等于 C = C + A
-=	相减后再赋值	C -= A 等于 C = C - A
*=	相乘后再赋值	C *= A 等于 C = C * A
/=	相除后再赋值	C /= A 等于 C = C / A
%=	求余后再赋值	C %= A 等于 C = C % A
<<=	左移后赋值	C <<= 2 等于 C = C << 2
>>=	右移后赋值	C >>= 2 等于 C = C >> 2
&=	按位与后赋值	C &= 2 等于 C = C & 2
^=	按位异或后赋值	C ^= 2 等于 C = C ^ 2
|=	按位或后赋值	C |= 2 等于 C = C | 2

&	返回变量存储地址	&a; 将给出变量的实际地址。
*	指针变量。	*a; 是一个指针变量
*/
func main() {
	var num int32 = 0
	//空接口定义为 interface{}，可以表示任何类型；vtest可以是一个变量也可以是一个函数或结构体
	var vtest interface{}

	if num == 0 {
		fmt.Println("IF")
	} else if num == 1 {
		fmt.Println("ELSE IF")
	} else {
		fmt.Println("ELSE")
	}

	switch num {
	case 0:
		fmt.Println("0")
		fmt.Println("默认情况下 case 最后自带 break 语句，匹配成功后就不会执行其他 case；也可以显式使用break")
		fmt.Println("使用 fallthrough 会强制执行后面的 case 语句，fallthrough 不会判断下一条 case 的表达式结果是否为 true")
		fallthrough
	case 1:
		fmt.Println("1")
		fallthrough
	case 2, 3:
		if num == 2 {
			fmt.Println("2或3")
		} else {
			break
		}
	default:
		fmt.Println("无论放在哪里都是最后执行")
	}

	num = -1
	switch {
	default:
		fmt.Println("无论放在哪里都是最后执行")
	case num == 0:
		fmt.Println("0")
		fmt.Println("使用 fallthrough 会强制执行后面的 case 语句，fallthrough 不会判断下一条 case 的表达式结果是否为 true")
		fallthrough
	case num == 1:
		fmt.Println("1")
		fallthrough
	case num == 2 || num == 3:
		fmt.Println("2或3")
	}

	//这里把int型变量赋值给空接口，空接口的类型就变为了int型
	vtest = 42
	fmt.Println("switch 语句还可以被用于 type-switch 来判断某个 interface 变量中实际存储的变量类型")
	switch vtemp := vtest.(type) {
	case int8, int16, int32, int64:
		fmt.Printf("vtest 的类型是int,值 = %d", vtemp)
		fmt.Println()
	case uint8, uint16, uint32, uint64:
		fmt.Printf("vtest 的类型是uint,值 = %d", vtemp)
		fmt.Println()
	case float32, float64:
		fmt.Printf("vtest 的类型是float,值 = %f", vtemp)
		fmt.Println()
	case complex64, complex128:
		fmt.Printf("vtest 的类型是complex,值 = %v", vtemp)
		fmt.Println()
	case string:
		fmt.Printf("vtest 的类型是string,值 = %s", vtemp)
		fmt.Println()
	case nil:
		fmt.Printf("vtest 的类型是nil,值 = %T", vtemp)
		fmt.Println()
	case func(int32) int32:
		fmt.Printf("vtest 的类型是func(int32) int32,也就是一个`参数为单个int32型，返回值为int32型的函数`")
		fmt.Println()
	default:
		fmt.Printf("vtest 的类型是未知类型")
		fmt.Println()
	}

	//创建2个int32类型的无缓冲通道
	var c1 chan int32 = make(chan int32)
	var c2 chan int32 = make(chan int32)
	//执行2个匿名函数;分别开启2个线程
	go func() {
		//在1秒后把100塞入c1
		time.Sleep(5 * time.Second)
		c1 <- 100
	}()
	go func() {
		//在1秒后把100塞入c1
		time.Sleep(1 * time.Second)
		c2 <- 200
	}()
	//select会先于2个匿名函数执行;case自带break效果；select会阻塞式等待某个case执行
	select {
	//case var tempnum = <- c1://无法显式类型声明在这里
	case tempnum := <-c1:
		fmt.Printf("select收到了匿名函数c1传来的值 = %d", tempnum)
		fmt.Println()
	case tempnum := <-c2:
		fmt.Printf("select收到了匿名函数c2传来的值 = %d", tempnum)
		fmt.Println()
	}
	select {
	//case var tempnum = <- c1://无法显式类型声明在这里
	case tempnum := <-c1:
		fmt.Printf("select收到了匿名函数c1传来的值 = %d", tempnum)
		fmt.Println()
	case tempnum := <-c2:
		fmt.Printf("select收到了匿名函数c2传来的值 = %d", tempnum)
		fmt.Println()
	}
}
